<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript Note</title>
</head>
<body>
<!-- 1:输出 -->
    <h2>学习js：1、输出</h2>
    <!-- 注：javascript不包含任何打印或输出的函数 -->
      <!-- 1.1弹出警告框 -->
      <button id="learnjs_1_1" onclick="ljs_1_1()">弹出警告框</button>
      <script>
        function ljs_1_1(){
            window.alert(5+6);
        }
      </script>

      <!--  1.2操作HTML元素  -->
        <!-- 使用 document.getElementById(id) 方法找到元素。
             使用 "id" 属性来标识 HTML 元素，并 innerHTML 来插入元素内容 -->
        <button id="learnjs_1_2" onclick="ljs_1_2()">点击修改文字</button>
        <script>
            function ljs_1_2(){
                var  learnjs_1_2_buttontext = document.getElementById("learnjs_1_2");
                if (learnjs_1_2_buttontext = "点击修改文字"){
                    document.getElementById("learnjs_1_2").innerHTML="修改完成";
                }
            }
        </script>

        <!-- 1.3直接写入文档内容 -->
         <!-- 在文档已完成加载后执行 document.write，整个 HTML 页面将被覆盖 -->
         <button id="learnjs_1_3" onclick="ljs_1_3()">将日期信息覆盖当前页面</button>
         <script>
            function ljs_1_3(){
                 document.write(new Date());
            }
         </script>
         <!-- 而通过操作文档流，可以解决覆盖页面的问题 -->
         <button onclick="ljs_1_3_1()">打开文档流》添加内容〉关闭文档流</button>
         <script>
         function ljs_1_3_1()
         {
             var txt1 = "This is a new window.";
             var txt2 = "This is a test.";
             document.open("text/html","replace");//加上
             document.writeln(txt1);
             document.write(txt2);
             document.close();//加上
         }
        </script>
        <!-- 该方法将关闭 open() 方法打开的文档流，并强制地显示出所有缓存的输出内容。
         如果您使用 write() 方法动态地输出一个文档，必须记住当你这么做的时候要调用 close() 方法，以确保所有文档内容都能显示。
         document.write() 不会隐式调用 document.close() 方法的，否则例 2 中将不会有 This is a new window. 内容了。
        一旦调用了close()，就不应该再次调用 write()，因为这会隐式地调用 open() 来擦除当前文档并开始一个新的文档。
        在载入页面后，浏览器输出流自动关闭。

        在此之后，比如延迟脚本 [setTimeout()] 或是 onload 执行的方法，
        任何一个对当前页面进行操作的 document.write()方法将打开—个新的输出流，它将清除当前页面内容(包括源文档的任何变量或值)。 -->

         <!-- 1.4 写入控制台 -->
          <!-- 点击f12进入浏览器开发者选项 -->
           <button id="learnjs_1_4" onclick="ljs_1_4()">控制台输出</button>
           <script>
               function ljs_1_4(){
                    a=2;b=3;c=a+b;
                   console.log("当前日期为" + new Date() + c);
               }
           </script>
           <!--  相比alert弹出后页面死亡，console输出后页面可以继续使用；同时console更适应结构化  -->
            <!-- console支持美化输出（添加样式），比如： -->
              <button id="learnjs_1_5" onclick="ljs_1_4_1()">美化的console.log</button>
              <script>
                  function ljs_1_4_1(){
                      console.log("%cHello World", "color:red;font-size:30px");
                  }
              </script>
            <!--  console也支持用%s等来表示变量，就像c语言那样  -->
            <button id="learnjs_1_4_2" onclick="ljs_1_4_2()" >输出到控制台</button>
            <script>
                function ljs_1_4_2(){
                    var hello = 'hello';
                    var one = 1;
                    console.log('%s world', hello)
                    console.log('%d + 1 = 2', one)
                }
            </script>
            
<!--  2、语法 -->
    <h2>2、语法</h2>
    <!-- 2.1 字面量-->
     <button onclick="ljs_2_1()" >将支持的字面量输出到控制台</button>
     <script>
         function ljs_2_1(){
            // %s 字符串
            console.log('%s', 'hello world')
            // %d 数字
            console.log('%d', 12e5)//输出为1200000,即12*10^5
                // %i 整数
                console.log('%i', 4.5)//输出为4
                // %f 浮点数
                console.log('%f', 1.35)//输出为1.35
            // %c 带有样式的字符串
            console.log('%c%s', 'color:red', 'hello world')
            // %o 对象
            console.log('%o', {name:'zhangsan', age:18})
            
            //数组
            //高级教程：【https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array】
            const fruits = [];
            fruits.push("banana", "apple", "peach");
            console.log("总共有"+fruits.length+"种水果"); // 输出为3（此处输出的是数组长度）
            for (let i = 0; i < fruits.length; i++) {
                var num = i + 1;//注意数组从0开始计数，展示给用户时需要+1。
                console.log("第"+ num +"个水果是"+fruits[i]);
            }
         }
     </script>
     <!-- 2.2 变量 -->
      <button onclick="ljs_2_2()">输出计算结果到控制台</button>
      <script>
         function ljs_2_2(){
             var a = 1;//var用于定义变量，同时使用等号来为变量赋值
             var b = 2;
             console.log("a="+a+",b="+b);

             var c = a + b;
             var d = a - b;
             var e = a * b;
             var f = a / b;
             var g = a % b;
             console.log("a+b="+c);//JavaScript使用算术运算符计算,使用赋值运算符给变量赋值
             console.log("a-b="+d);
             console.log("a*b="+e);
             console.log("a/b="+f);
             console.log("a%b="+g);

             //除此之外js还存在 条件，比较及逻辑运算符	==  != <  >  它们用于在 JS 比较运算符中描述

             //注释：使用双斜杠，注释中的语句不予执行。
             //console.log("我不会执行");

            //关于数据类型

            var x = 16;                                  // Number 通过数字字面量赋值 
            var points = x * 10;                              // Number 通过表达式字面量赋值
            var lastName = "Johnson";                         // String 通过字符串字面量赋值
            var cars = ["Saab", "Volvo", "BMW"];              // Array  通过数组字面量赋值
            var person = {firstName:"John", lastName:"Doe"};  // Object 通过对象字面量赋值
         }
     </script>
     <!-- 2.2.1 大小写敏感-->
      <!-- 注意：javascript对大小写是敏感的。比如getElementById()与getElementByID()是不同的 -->
       <!-- 同时，变量名myVar和myvar不是同一个变量。 -->
        <button onclick="ljs_2_2_1_myFunction()">点击一下</button>
        <script>
            // 由于javascript的大小写敏感，所以只会输出Hello World。
            function ljs_2_2_1_myFunction() {
                var myVar = "Hello World";
                var myvar = "Goodbye World";
                console.log(myVar);
            }
            function ljs_2_2_1_myfunction() {
                var myVar = "Good World";
                var myvar = "Bad World";
                console.log(myVar);
            }
        </script>

    <!-- 2.2.2 typeof的小缺陷 -->
         <!--   有个情况需要特别注意: typeof 不能用来判断是 Array 还是Object
                var arr = [] typeof(arr) === 'object' // true
                结果为 true。
                当然你可以使用其他方式来判断： -->
                <button onclick="ljs_2_2_2()">是数组吗</button>
                <script>
                function ljs_2_2_2(){
                    var cars=new Array();
                    cars[0]="Saab";
                    cars[1]="Volvo";
                    cars[2]="BMW";

                    if (Array.isArray) {
                        if(Array.isArray(cars)) {
                            console.log("isArray方法认为这是数组");
                        }
                    }
                    if (cars instanceof Array) {
                            console.log("instanceof方法认为这是数组");
                    }
                }
                </script>

    <!-- 2.2.3 关于开发规范 -->
        <!-- 关于命名 -->
         <script>
        /*
        1.匈牙利命名方式：变量名+对象描述 整数i 浮点fl 布尔b 字符串s 数组a 对象o 函数fn 正则re 例：iAge = 18;
        2.驼峰命名：
            （1）全部小写：单词与单词间全部用下划线分割
            （2）大小写混合：每个单词的第一个字母大写,例：jsBiJi 
        */
       //这里顺便介绍了js的注释，有行注释和块注释两种。
         </script>

    <!-- 2.2.4 一条语句也可以定义多个变量 -->
     <button onclick="ljs_2_2_4()">输出多个变量</button>
        <script>
            function ljs_2_2_4(){
            var iAge = 18,
                sName = 'js',
                bIsTrue = true,
                undefinedValue;//未使用值来声明的变量，其值实际上是undefined。
            console.log(iAge,sName,bIsTrue,undefinedValue);
            }
        </script>

    <!-- 2.2.5 ES6:使用let和const声明变量 -->
        <button onclick="ljs_2_2_5()">ES6:使用let和const声明变量</button>
        <script>
            function ljs_2_2_5(){
                let head = 'hello';//定义限定范围内作用域的变量
                const foot = 'world';//定义一个常量
                console.log(head,foot);
            }
        </script>

<!-- 3、数据类型 -->
 <h2>3 : 数据类型</h2>
    <!-- 值类型（基本类型）：字符串（String）、数值（Number）、布尔值（Boolean）、空（null）、未定义（undefined）、Symbol -->
    <!-- 其中Symbol 是 ES6 新增的类型，它表示一个唯一的值，一般用于对象属性的键 -->
    <!-- 引用数据类型（对象类型）：对象（Object）、数组（Array）、函数（Function） -->
    <!-- 特殊的对象：正则表达式（RegExp）、日期（Date） -->
     
    <!-- 3.1 javascript拥有动态类型 -->
     <script>
        var ljs_3_1;//此时ljs_3_1为undefined类型
        ljs_3_1 = 1;//此时ljs_3_1为Number类型
        ljs_3_1 = 'hello';//此时ljs_3_1为String类型
        ljs_3_1 = true;//此时ljs_3_1为Boolean类型
        ljs_3_1 = null;//此时ljs_3_1为null类型
    </script>
    <!-- 变量的数据类型可以通过typeof操作符来查看 -->
     <button onclick="ljs_3_1_1()">查看变量的数据类型</button>
     <script>
        var ljs_3_1_1_1 = typeof "string";
        var ljs_3_1_1_2 = typeof 123;
        var ljs_3_1_1_3 = typeof true;
        var ljs_3_1_1_4 = typeof null;
        var ljs_3_1_1_5 = typeof [1,2,3,4]             // 返回 object
        var ljs_3_1_1_6 = typeof {name:'John', age:34} // 返回 object


        function ljs_3_1_1(){
            console.log(ljs_3_1_1_1);//string
            console.log(ljs_3_1_1_2);//number
            console.log(ljs_3_1_1_3);//boolean
            console.log(ljs_3_1_1_4);//object 用typeof检测null返回是object。
            console.log(ljs_3_1_1_5);//object 在javascript中，数组是一种特殊的对象类型，因此返回object。
            console.log(ljs_3_1_1_6);//object
        }
     </script>
    <!-- 3.2 数据类型的表示 -->
     <button onclick="ljs_3_2()">数据类型的表示</button>
     <script>
        function ljs_3_2(){
            // 字符串
            var ljs_3_2_1 = "有个问题：";//双引号 表示变量为字符
            var ljs_3_2_2 = '是谁干的？';//单引号 也可以表示变量为字符
            var ljs_3_2_3 = "他说：'那不是我干的'。"//双引号里可以包着单引号
            var ljs_3_2_4 = '他说:"也不是我干的"。';//单引号里可以包着双引号
            var ljs_3_2_5 = '又有人说：\'难道是我干的吗\'？';//单引号里可以包着单引号，只需在单引号前加反斜杠
            var ljs_3_2_6 = "还有人说：\"我不知道是谁干的\"。"//双引号里可以包着双引号，只需在双引号前加反斜杠
            console.log("字符串输出如下：");
            console.log(ljs_3_2_1+ljs_3_2_2+ljs_3_2_3+ljs_3_2_4+ljs_3_2_5+ljs_3_2_6);//上述字符串均可正常输出
            console.log(" ");

            //数字
            var ljs_3_2_7 = 123;
            var ljs_3_2_8 = 123.00;//小数点可带可不带，输出均为123

            var ljs_3_2_9 = 123e5;
            var ljs_3_2_10 = 123e-5;//极大或极小的数字可以用科学（指数）计数来表示
            console.log("数字输出如下：");
            console.log(ljs_3_2_7+" "+ljs_3_2_8+" "+ljs_3_2_9+" "+ljs_3_2_10);
            console.log(" ");

            //对象
            var ljs_3_2_11 = {
                name:"js",
                age:18,
                sex:"男"
            };
            console.log("对象输出如下：");
            console.log(ljs_3_2_11.age);//输出对象属性,共有两种寻址方式
            console.log(ljs_3_2_11["age"]);
            console.log(" ");

            //声明变量属性：您可以使用关键词new来对新变量声明其类型
            var ljs_3_2_12 = new String("js");
            var ljs_3_2_13 = new Number(18);
            var ljs_3_2_14 = new Boolean(true);
            var ljs_3_2_15 = new Object({name:"js",age:18,sex:"男"});//输出 [object Object]
            var ljs_3_2_16 = new Array("js","18","男");
            var ljs_3_2_17 = new Function();
            console.log("声明变量属性如下：");
            console.log(ljs_3_2_12+"    "+ljs_3_2_13+"    "+ljs_3_2_14+"    "+ljs_3_2_15+"    "+ljs_3_2_16+"    "+ljs_3_2_17);
            console.log(" ");
        }
     </script>
<!-- 4、函数 -->
     <h2>4 : 函数</h2>
     <button onclick="ljs_4_0_1('bro','m',3)">调用带参数的函数 1</button>
     <button onclick="ljs_4_0_1('laotie','niubi',666)">调用带参数的函数 2</button>
     <script>
        function ljs_4_0_1(text1,text2,num){//接受3个参数
            console.log(text1+' '+text2+num);//输出bro m3或laotie niubi666。
                                             //因为函数是灵活的，使用不同的参数调用函数，输出结果也会不同
        }
     </script>
     
     <button onclick="ljs_4_0_3()">调用有返回值的函数</button>
     <button onclick="ljs_4_0_4(1,2)">使用1、2调用【ljs_4_4】函数</button>
     <button onclick="ljs_4_0_4(2,1)">使用2、1调用【ljs_4_4】函数</button>

     <script>
        function ljs_4_0_2(){
            var ljs_4_0_2_1 = 666
            return ljs_4_0_2_1;
        }
        function ljs_4_0_3(){
            var result = ljs_4_0_2();//调用函数并把返回值赋值给result
            console.log(result);
        }

        function ljs_4_0_4(a,b){
            var x;
            if(a>b){
                console.log('a大于b');
                return;//仅仅希望退出函数时可以使用return语句，返回值可选。
                console.log('return已完成。');//输出return后的代码将不会被执行。
            }
            x=a+b;//如本代码，当a大于b时，上面的代码将退出函数，并不会计算总和。
            console.log(x);
        }
     </script>

     <!-- 4.1 关于变量的生命周期 -->

     <!-- javascript 变量的生命周期： -->
      <script>
        var ljs_4_1_1 = 666;//全局变量，声明时开始，函数运行后死亡
        function ljs_4_1_2(){
            var ljs_4_1_2_1 = 666;//局部变量，声明时开始，页面关闭后死亡
        }
        ljs_4_1_2();
      </script>

      <!-- 4.2 关于未声明的变量分配值 -->

      <!-- 将值赋给未声明的变量，这个变量将被自动作为window的一个属性 -->
      <div style="background-color: black;">
        <h3 style="color: white;">尝试将未声明变量的值打印到当前的div容器中</h3>
        <button onclick="ljs_4_2_3()">尝试定义var3【没有var声明的属性】</button>
        <button onclick="ljs_4_2_1()">尝试删除var1【没有var声明的属性】</button>
        <button onclick="ljs_4_2_2()">尝试删除var2【不可配置全局属性】</button>
        

        <h4 style="color: aqua;">结果 :</h4><p id="ljs_4_2_show" style="color: white;"></p>
      </div>
      <script>
        ljs_4_2_1_1 = 666;//var1:未声明变量，自动分配给window
        var ljs_4_2_1_2 = 666;//var2:不可配置全局属性
        ljs_4_2_1_3 = "";//var3:未声明变量，自动分配给window
        ljs_4_2_update();//更新显示

        function ljs_4_2_1(){
            delete ljs_4_2_1_1;//删除var1。执行后在控制台可以看到报错：变量未定义
            ljs_4_2_update();//更新显示【控制台报错】
        }

        function ljs_4_2_2(){
            delete ljs_4_2_1_2;//删除var2，可以被删除
            ljs_4_2_update();//更新显示【实际上不会更新，因为值已被删除】
        }

        function ljs_4_2_3(){
            ljs_4_2_1_3 = 666;//定义var3:未声明变量，自动分配给window
            ljs_4_2_update();//更新显示【】var3变为666
        }

        function ljs_4_2_update(){//更新显示方法
            document.getElementById("ljs_4_2_show").innerHTML ="var 1:" +ljs_4_2_1_1+" var 2:"+ljs_4_2_1_2+" var 3:"+ljs_4_2_1_3;
        }
       
      </script>
    <!-- 补充：4.2 关于作用域 -->
    <!-- <script src="./js/4_2:关于作用域.js"></script> -->

    <!-- 5 : javascript事件 -->
     <h2>5 : javascript事件</h2>
     <div style="border:3px solid black;">

     <button onclick="getElementById('ljs_5_0_showdate').innerHTML='现在时间是：'+Date()">点击添加html元素:现在几点了？</button>
     <!-- 在button标签中直接添加onclick属性并添加代码 -->

     <p id="ljs_5_0_showdate">现在时间是：没人问我。</p>
    <!-- 这里的内容将被更新 -->

     <button onclick="this.innerHTML='现在时间是：'+Date()">现在时间是：也没人问我。</button>
     <!-- 同时也可以使用this来修改自身属性，此处使用innerhtml。 -->

     <button onclick="ljs_5_0_displayDate()">现在时间是：也可以问我</button>
     <script>
       function ljs_5_0_displayDate(){
            document.getElementById("ljs_5_0_showdate").innerHTML="现在时间是："+Date();
        }
     </script>
    <!-- 通常使用上述方法，调用事件属性。 -->
     <!-- 当然，javascript可以控制更多html事件，详见https://www.runoob.com/jsref/dom-obj-event.html -->

    </div>

    <!-- 6：字符串 -->
     <h2>6 : 字符串</h2>
    
     <!-- script 3.2中已经介绍了单双引号的使用细节，此处不再赘述。 -->
      <div style="border:3px solid black;">
        <p>你可以使用索引位置来访问字符串。</p>
        <button onclick="ljs_6_0_1()" id="learnjs_6_1">告诉你这行字的第五个字是什么</button>
        <script>
            const ljs_6_0_1_1 = document.getElementById("learnjs_6_1");
            function ljs_6_0_1(){
                alert(ljs_6_0_1_1.innerHTML[4]);//索引值从0开始，这意味着第五个字的索引值应为4.
            }
        </script>

        <p>你可以使用length属性来获取字符串的长度。</p>
        <button onclick="ljs_6_0_2()" id="learnjs_6_2">这行字只有8个字</button>
        <script>
            const ljs_6_0_2_1 = document.getElementById("learnjs_6_2");
            function ljs_6_0_2(){
                alert('都说了有'+ljs_6_0_2_1.innerHTML.length+'个字，你还不信');//获取字符串长度
            }
        </script>

        <p>字符串也可以使用索引位置来修改。</p>
        <button onclick="ljs_6_0_3()" id="learnjs_6_3">修改这列字</button>
        <script>
            const ljs_6_0_3_1 = document.getElementById("learnjs_6_3");
            function ljs_6_0_3(){
                ljs_6_0_3_1.innerHTML = ljs_6_0_3_1.innerHTML.replace('列','行');//使用replace方法来修改某个字
            }
        </script>
      </div>

      <p>对于特殊字符</p>
      <!-- javascript中，可以使用反斜杠来转义特殊字符。 -->
       <!-- 常用的特殊字符如下：\' 单引号 \" 双引号 \n 换行 \r 回车 \t 制表符tab \b 退格符 \f 换页符 \\ 反斜杠" -->

       <!-- 字符串可以是对象。但是不建议创建，它不仅会拖慢执行速度，还可能产生其他副作用 -->
        <button onclick="ljs_6_1_3()">
            <p style="color: rgb(255, 166, 0);">new String('hello world')</p>和<p style="color: rgb(255, 166, 0);"> 'hello world' 一样吗？</p>
        </button>

        <script>
            var ljs_6_1_1 = new String('hello world');//定义String对象
            var ljs_6_1_2 = 'hello world';//定义原始值字符串，它没有属性和方法，因为不是对象
            function ljs_6_1_3(){
                console.log(ljs_6_1_1 === ljs_6_1_2);
                //输出为false，因为x是字符串但y是对象。
                //此处的===为绝对相等，即数据类型和值必须完全相等。
            } 
        </script>

        <div style="border: 3px solid black;">
            <p id="learnjs_6_4"></p>
            <script>
                var ljs_6_4_string = '字符串具有一些属性，针对这句话，你可以先了解下面的三个属性';
                document.getElementById('learnjs_6_4').innerHTML = ljs_6_4_string;
            </script>
            
            <button onclick="ljs_6_4_constructor()">创建字符串属性的函数</button>
            <script>
                function ljs_6_4_constructor(){
                    console.log(ljs_6_4_string.constructor);
                }
            </script>

            <button onclick="console.log(ljs_6_4_string.length)">返回字符串长度</button>
            <!-- prototype 允许您向对象添加属性和方法-->

            <!-- 6.5 字符串方法 可以使用下面提供的工具来尝试这些方法，更多方法实例详见https://www.runoob.com/jsref/jsref-obj-string.html -->
<div style="border: 3px solid black;">
    <h3>字符串方法操作</h3>
    <p>输入字符串: <input type="text" id="ljs_6_5" value="Hello, World!"></p>
    <p>选择方法:
        <select id="stringMethodSelect">
            <option value="charAt">charAt() - 返回指定索引位置的字符</option>
            <option value="charCodeAt">charCodeAt() - 返回指定索引位置字符的 Unicode 值</option>
            <option value="concat">concat() - 连接两个或多个字符串，返回连接后的字符串</option>
            <option value="fromCharCode">fromCharCode() - 将 Unicode 转换为字符串</option>
            <option value="indexOf">indexOf() - 返回字符串中检索指定字符第一次出现的位置</option>
            <option value="lastIndexOf">lastIndexOf() - 返回字符串中检索指定字符最后一次出现的位置</option>
            <option value="localeCompare">localeCompare() - 用本地特定的顺序来比较两个字符串</option>
            <option value="match">match() - 找到一个或多个正则表达式的匹配</option>
            <option value="replace">replace() - 替换与正则表达式匹配的子串</option>
            <option value="search">search() - 检索与正则表达式相匹配的值</option>
            <option value="slice">slice() - 提取字符串的片断，并在新的字符串中返回被提取的部分</option>
            <option value="split">split() - 把字符串分割为子字符串数组</option>
            <option value="substr">substr() - 从起始索引号提取字符串中指定数目的字符</option>
            <option value="substring">substring() - 提取字符串中两个指定的索引号之间的字符</option>
            <option value="toLocaleLowerCase">toLocaleLowerCase() - 根据主机的语言环境把字符串转换为小写</option>
            <option value="toLocaleUpperCase">toLocaleUpperCase() - 根据主机的语言环境把字符串转换为大写</option>
            <option value="toLowerCase">toLowerCase() - 把字符串转换为小写</option>
            <option value="toString">toString() - 返回字符串对象值</option>
            <option value="toUpperCase">toUpperCase() - 把字符串转换为大写</option>
            <option value="trim">trim() - 移除字符串首尾空白</option>
            <option value="valueOf">valueOf() - 返回某个字符串对象的原始值</option>
        </select>
    </p>
    <p>参数: <input type="text" id="methodParams"></p>
    <button onclick="executeStringMethod()">执行方法</button>
    <p>结果: <span id="methodResult"></span></p>
</div>

<script>
    function executeStringMethod() {
        const ljs_6_5 = document.getElementById('ljs_6_5').value;
        const method = document.getElementById('stringMethodSelect').value;
        const params = document.getElementById('methodParams').value;
        let result;

        try {
            switch (method) {
                case 'charAt':
                    result = ljs_6_5.charAt(parseInt(params));
                    break;
                case 'charCodeAt':
                    result = ljs_6_5.charCodeAt(parseInt(params));
                    break;
                case 'concat':
                    result = ljs_6_5.concat(params);
                    break;
                case 'fromCharCode':
                    result = String.fromCharCode(parseInt(params));
                    break;
                case 'indexOf':
                    result = ljs_6_5.indexOf(params);
                    break;
                case 'lastIndexOf':
                    result = ljs_6_5.lastIndexOf(params);
                    break;
                case 'localeCompare':
                    result = ljs_6_5.localeCompare(params);
                    break;
                case 'match':
                    result = ljs_6_5.match(new RegExp(params));
                    break;
                case 'replace':
                    result = ljs_6_5.replace(new RegExp(params), '替换内容');
                    break;
                case 'search':
                    result = ljs_6_5.search(new RegExp(params));
                    break;
                case 'slice':
                    result = ljs_6_5.slice(parseInt(params));
                    break;
                case 'split':
                    result = ljs_6_5.split(params);
                    result = result.join(', '); // 将数组转换为字符串以便显示
                    break;
                case 'substr':
                    result = ljs_6_5.substr(parseInt(params));
                    break;
                case 'substring':
                    result = ljs_6_5.substring(parseInt(params));
                    break;
                case 'toLocaleLowerCase':
                    result = ljs_6_5.toLocaleLowerCase();
                    break;
                case 'toLocaleUpperCase':
                    result = ljs_6_5.toLocaleUpperCase();
                    break;
                case 'toLowerCase':
                    result = ljs_6_5.toLowerCase();
                    break;
                case 'toString':
                    result = ljs_6_5.toString();
                    break;
                case 'toUpperCase':
                    result = ljs_6_5.toUpperCase();
                    break;
                case 'trim':
                    result = ljs_6_5.trim();
                    break;
                case 'valueOf':
                    result = ljs_6_5.valueOf();
                    break;
                default:
                    result = '未知的方法';
            }
        } catch (e) {
            result = '执行错误: ' + e.message;
        }

        document.getElementById('methodResult').innerText = result;
    }
</script>
        </div>

        <!-- 7. 模板字符串 -->
         
        <!-- 
            模板字符串（Template Strings）是一个字符串字面量，它允许在字符串中嵌入表达式。
            在模板字符串中，可以使用反引号（`）来定义字符串，并且可以在其中嵌入表达式。
            表达式以${}的形式表示，其中包含要嵌入的字符串。
            
            以下是一个简单的示例：
        -->

        <button onclick="ljs_7_0_1()" >在控制台输出name</button>

        <script>
            const name = 'John';
            const greeting = `Hello, ${name}!`;
            
            function ljs_7_0_1(){
            console.log(greeting); // 输出：Hello, John!
            }
        </script>

        <!-- 其中：
            string text将成为模板字面量的一部分字符串文本，几乎允许所有字符，包括换行符和其他空白字符。
            但是除非使用了标签函数，否则无效的转义序列将导致语法错误。 

            expression表示要插入当前位置的表达式，其值被转换为字符串或传递给tagFunction。

            tagFunction 如果指定，将使用模板字符串数组和替换表达式调用它，返回值将成为模板字变量的值。
        -->
        
        <button onclick="ljs_7_0_2()">在控制台输出一段话</button>
        <script>
            let ljs_7_0_2_text = //本示例说明：模板字符串支持多行文本（无需使用特殊的转义字符），且支持同时使用单引号和双引号
            `
            他说："当'梦'醒过来的时候，
                  一切都将回到起点。"
                          他在做梦。
            `;

            function ljs_7_0_2(){
                console.log(ljs_7_0_2_text);
            }
        </script>

        <!-- 若要转义模板字面量中的反引号，需要在前面加一个反斜杠 -->

        <button onclick="ljs_7_0_3()" >`\``==="`"吗</button>

        <script>
            function ljs_7_0_3(){
                console.log(`\``==="`");//输出true。
            }
        </script>

        <!-- 
            除了普通字符串外，模板字面量还可以包含占位符：一种由美元符号和大括号分隔的嵌入式表达式 ${ expression} 
            字符串和占位符被传递给一个函数（要么是默认函数要么是自定义函数）。
            默认函数（当未提供自定义函数时）只执行字符串插值来替换占位符，然后将这些部分拼接到一个字符串中。
        -->
        <button onclick="ljs_7_0_4()">在控制台输出问题和答案</button>
        <script>
            const question = 'Why my life is so bad?';
            const answer = 'Because you always sleeping.';

            function ljs_7_0_4(){
                console.log(`
                Q: ${question} 
                A:${answer}
                
                Don't be lazy!
                `);
            }
        </script>

        <!-- 模板字符串也允许你在字符串中引用变量、执行函数调用和进行任意的javascript表达式 -->
         <button onclick="ljs_7_0_5()">在控制台输出：尝试在模板字符串使用表达式</button>
         <script>
            let coins_total = 213;
            let coins_per_pc = 4 ;
            function pc_per_song(people){
                switch (people) {
                    case 1:
                        return 3;
                    case 2:
                        return 4;
                }
            }

            let play_maimai = `
                你共拥有${coins_total}个硬币，
                每${coins_per_pc}枚硬币可以玩一局舞萌DX，
                共可以${(coins_total/coins_per_pc).toFixed(0)}次舞萌DX。
                普通模式单刷的话也就是${pc_per_song(1)*(coins_total/coins_per_pc).toFixed(0)}首歌，
                拼机可以玩${pc_per_song(2)*(coins_total/coins_per_pc).toFixed(0)}首歌。
                至于剩下的${coins_total%coins_per_pc}颗可以扔进推币机了。
                `;//注：上述事例使用了函数调用与变量引用。
            
            function ljs_7_0_5(){
                console.log(play_maimai);
            }

         </script>

         <!-- 模板字符串也可以当作html模板使用，实例如下 -->
          <div style="border: 3px solid black;">
          <button onclick="ljs_7_0_6()">在控制台输出：尝试html模板</button>
          <div id="ljs_7_0_6_div">点击后内容将在这里生成</div>
          <script>
            function ljs_7_0_6(){
                let name = 'h1标签';
                let age = 25;
                let html = `
                <div>
                    <h1>${name}</h1>
                    <p>${age}</p>
                </div>
                `;
                document.getElementById('ljs_7_0_6_div').innerHTML = html;
            }
          </script>
          </div>

        <!-- 8、关于运算符 -->
         <div style="border: 3px solid black;">
            <p>如果y=5，那么：</p>
            <button onclick="ljs_8_0_1()" >打印到控制台</button>
            <script>
                let y = 5;
                function ljs_8_0_1(){
                    console.log(`x=y+2   | x=${y+2} y=${y}`);
                    console.log(`x=y-2   | x=${y-2} y=${y}`);
                    console.log(`x=y*2   | x=${y*2} y=${y}`);
                    console.log(`x=y/2   | x=${y/2} y=${y}`);
                    console.log(`x=y%2   | x=${y%2} y=${y}`);
                    console.log(`x=y**2  | x=${y**2} y=${y}`);
                }
            </script>
            <p>x=y+2   | x=7 y=5</p>
            <p>x=y-2   | x=3 y=5</p>
            <p>x=y*2   | x=10 y=5</p>
            <p>x=y/2   | x=2.5 y=5</p>
            <p>x=y%2   | x=1 y=5</p>
            <p>x=y**2  | x=25 y=5</p>
            <!-- 自增/自减 -->
            <p>x=y++   | x=5 y=6</p>
            <p>x=++y   | x=6 y=6</p>
            <p>x=y--   | x=5 y=4</p>
            <p>x=--y   | x=4 y=4</p>
         </div>
        
         <!-- 8.1 +号可以用于连接字符串 -->
          <button id="ljs_8_1" onclick="ljs_8_1()" >点击修改文字</button>
          <script>
              let ljs_8_1_text = 'hello';
              function ljs_8_1(){
                  ljs_8_1_text += ' world';
                  document.getElementById('ljs_8_1').innerHTML = ljs_8_1_text;
              }
          </script>
            <!-- 数字相加得到和，数字与字符串相加返回字符串 -->
             <button id="ljs_8_1_1" onclick="ljs_8_1_1()" > 输出5+5和“5”+5和“hello”+5到控制台 </button>
             <script>
                 function ljs_8_1_1(){
                     console.log(5+5);//输出10
                     console.log('5'+5);//输出"55"
                     console.log('hello'+5);//输出"hello5"
                 }
             </script>

             <!-- 8.2 比较运算符 -->
             <div style="border: 3px solid black;">
                 <p>如果x=5，那么：</p>
                 <button onclick="ljs_8_2_1()" >打印到控制台</button>
                 <script>
                     let x = 5;
                     function ljs_8_2_1(){
                         console.log(`x>2   | ${x>2}`);//大于，输出true
                         console.log(`x>=2  | ${x>=2}`);//大于等于，输出true
                         console.log(`x<2   | ${x<2}`);//小于，输出false
                         console.log(`x<=2  | ${x<=2}`);//小于等于，输出false
                         console.log(`x==2  | ${x==2}`);//等于，输出false
                         console.log(`x!=2  | ${x!=2}`);//不等于，输出true
                         console.log(`x===2  | ${x===2}`);//严格等于，输出false
                         console.log(`x!==2  | ${x!==2}`);//严格不等于，输出true
                         console.log(`x=='5'  | ${x=='5'}`);//与字符串的`5`进行等于比较，输出true
                         console.log(`x==='5'  | ${x==='5'}`);//与字符串的`5`进行严格等于比较，输出false
                         console.log(`x!=='5'  | ${x!=='5'}`);//与字符串的`5`进行严格不等于比较，输出true
                     }
                 </script>
                 <!-- 可以运用的场景，如条件语句 -->
                  <button onclick="ljs_8_2_2(18)" >我可以进去吗？</button>
                  <script>
                      function ljs_8_2_2(age){
                         if(age>=18){
                             console.log('可以进去');
                         }else{
                             console.log('不可以进去');
                         }
                     }
                  </script>

                  <!-- 8.3 逻辑运算符 -->
                   <button onclick="check(1)">一号按钮</button>
                   <button onclick="check(2)">二号按钮</button>
                   <button onclick="check_logic()">检查逻辑</button>
                   <script>
                       var check_fir = false;
                       var check_sec = false;

                       function check(num){
                            switch(num){
                                case 1:
                                    check_fir = true;
                                    break;
                                case 2:
                                    check_sec = true;
                                    break;    
                            }
                       }

                       function check_logic(){
                           if(check_fir || check_sec){
                            //or运算符  其中一个条件正确即true
                            //太阳从东方升起 || 太阳从西方升起 true
                               console.log('其中一个按钮点过了');
                           }
                       
                          if(check_fir && check_sec){
                            //and运算符 需两个条件全部正确
                            //太阳从东方升起 && 太阳从西方升起 false
                            //太阳从东方升起 && 太阳从西边落下 true
                           console.log('两个按钮都点过了');
                          }
                          if(!check_fir && !check_sec){//not运算符
                           console.log('两个按钮都没有点过');
                          } 

                        }
                   </script>
             </div>

        <!-- 9. 条件语句 -->
         <h3>条件语句</h3>

         <button onclick="ljs_9_0_1()">尝试使用if</button>
         <script>
            function ljs_9_0_1(){
                var time = new Date().getHours();

                if(6<time<20 || time !=12){//if后写条件；
                    console.log("good day");
                }else if(time == 12){//else if允许一个代码块包含更多的条件
                    console.log("good zhongwu.")
                }
                else{//else后的执行建立在之前的if条件不成立的情况。
                    console.log("good night");
                }
            }
            
         </script>

        <!-- 使用switch语句 -->
        <button onclick="ljs_9_0_2(0)">0</button>
        <button onclick="ljs_9_0_2(1)">1</button>
        <button onclick="ljs_9_0_2(2)">2</button>

        <script>
            function ljs_9_0_2(num){
                switch(num){
                    case 0://case后的值如果和上面的参数相同，则执行对应代码块
                        console.log("0");
                        break;//break阻止继续执行下面的case代码
                    case 1:
                        console.log("1");
                        break;
                    case 2:
                        console.log("2");
                        break;
                    default://默认输出
                        console.log("error");
                }
            }
        </script>

    <!-- 10. 循环 -->
     <button onclick="ljs_10_0_1()">输出4个汽车品牌</button>
     <button onclick="ljs_10_0_2()">你用过这些软件吗</button>
     <script>
        var ljs_10_0_1_cars = ["BMW","Volvo","Saab","Ford"];

        function ljs_10_0_1(){
            //    ⬇(1)   ⬇(2)         ⬇(3)
            for (var i=0;i<ljs_10_0_1_cars.length;i++){ //if（代码1:代码块开始前运行；代码2：定义运行循环的条件；代码3:循环已被执行后再执行）
                console.log(ljs_10_0_1_cars[i]);
            }
        }

        // 通常，代码1可以被省略。
        var ljs_10_0_1_i = 0;
        var ljs_10_0_1_software = ["Visual Studio","Visual Studio Code","Sublime Text","Atom","Notepad++","Brackets","WebStorm","IntelliJ IDEA","Eclipse","NetBeans","Code::Blocks","CodeLite","CodeRunner","CodeRunner","CodeRunner","CodeRunner","CodeRunner","CodeRunner","CodeRunner","CodeRunner","CodeRunner","CodeRunner","CodeRunner","CodeRunner","CodeRunner","CodeRunner","CodeRunner","CodeRunner"];

        function ljs_10_0_2(){
            for (var ljs_10_0_1_i=0;ljs_10_0_1_i<ljs_10_0_1_software.length;){
                console.log(ljs_10_0_1_software[ljs_10_0_1_i]);
                ljs_10_0_1_i++;
            }
        }
     </script>
     <!-- 而代码2同样可以被省略，但是必须在循环中提供break，否则可能会因为循环无法停下来而导致浏览器崩溃。 -->
     <button onclick="ljs_10_0_3()">启动循环，但是没有语句1 2</button>
     <button onclick="ljs_10_0_4()">启动循环，但是没有语句1 2 3</button>
     <script>
        var ljs_10_0_3_i = 0;

         function ljs_10_0_3(){
            for (;;ljs_10_0_3_i++){
                if (ljs_10_0_3_i<=10000){
                      console.log(ljs_10_0_3_i);//输出0-10000
                 }else{
                    break;// >10000时跳出循环
                 }
             }
        }

         //其实语句3也是可以省略的，比如内部有相应的代码时。
         function ljs_10_0_4(){
            for (;;){
                if (ljs_10_0_4_i<=10000){
                      console.log(ljs_10_0_4_i);//输出0-10000
                      ljs_10_0_4_i++;
                 }else{
                    break;// >10000时跳出循环
                 }
             }
        }

     </script>

     <!-- for/in循环遍历对象的属性 -->

     <button onclick="ljs_10_0_5()">查看档案</button>
     <script>
        var ljs_10_0_5_obj={
            name:"ljs",
            age:18,
            sex:"男"
        }
        function ljs_10_0_5(){
            for(var x in ljs_10_0_5_obj){//x为属性名
                console.log(ljs_10_0_5_obj[x]);
            }
        }
     </script>

     <!-- 10.1 while 循环 -->
      <!-- while循环会在指定条件为真时执行代码块 -->
       <button onclick="ljs_10_1_1()">输出1-5</button>
        <script>
            function ljs_10_1_1(){
                var i=1;
                while(i<=5){
                    console.log(i);
                    i++;//切记增加约束，如果忘记增加条件中所用变量的值，该循环将永远不会结束，可能导致浏览器崩溃。
                }
            }
        </script>
        <button onclick="ljs_10_1_2()">输出1-5</button>
        <button onclick="ljs_10_1_3()">输出1</button>

        <script>
        function ljs_10_1_2(){
            var i=1;
            do{//do-while循环，先执行，再判断。
                console.log(i);
                i++;
            }while(i<=5);
        }

        function ljs_10_1_3(){
            var i=1;
            do{//由于先执行后判断，即使条件为false也会执行一次，因为代码块会在条件被测试前执行。
                console.log(i);
                i++;
            }while(i>5);//i>5不成立，为false。
        }
        </script>

    <!-- 10.2 关于break和continue -->
     <button onclick="ljs_10_2_1()">输出1-50中不能被2整除的数</button>
     <script>
        function ljs_10_2_1(){
            for(var i=1;;i++){
                if(i%2==0){
                    continue;//继续执行，跳过本次循环。
                }else if(i>50){
                    break;//跳出循环。
                }
                console.log(i);
            }
        }
     </script>

        <button onclick="ljs_10_2_2()">输出四个花色</button>
        <script>
            function ljs_10_2_2(){
                card=["黑桃","红桃","梅花","方片","方花","梅片"];
                list:{
                    console.log(card[0]);//输出
                    console.log(card[1]);//输出
                    console.log(card[2]);//输出
                    console.log(card[3]);//输出
                    break list;//跳出   在第4个项目（即[3]处break，此时下面的内容将不再输出。
                    console.log(card[4]);//不输出
                    console.log(card[5]);//不输出
                }
            }
        </script>

        <!-- 11、关于 typeof/null/undefined -->
        <!-- 有关数据类型的基础，可以看 3.数据类型 ，command+点击下面onclick中的方法以跳转-->
        <p onclick="ljs_3_1_1()"></p>
        
        <!-- 可以使用null、undefined来清空对象 -->
         <script>
            var ljs_11_0_1 = null;     //值为null，类型为object
            var ljs_11_0_2 = undefined;//值为undefined，类型为undefined
         </script>

         <button onclick="ljs_11_0_3()">null和undefined的区别？</button>
         <script>
            function ljs_11_0_3(){
                console.log("null == undefined //"+(null == undefined));
                console.log("null === undefined //"+(null === undefined));
            }
         </script>

         <!-- 12 类型转换 -->
          <button onclick="ljs_12_0_1()">constructor</button>
          <script>
            //constructor 属性返回所有 JavaScript 变量的构造函数。
            function ljs_12_0_1(){
                console.log("string".constructor);              // 返回函数 String()  { [native code] }
                console.log((123).constructor);                 // 返回函数 Number()  { [native code] }
                console.log(true.constructor);                  // 返回函数 Boolean() { [native code] }
                console.log([1,2,3,4].constructor);             // 返回函数 Array()   { [native code] }
                console.log({name:"ljs",age:18}.constructor);   // 返回函数 Object()  { [native code] }
                console.log(function(){}.constructor);          // 返回函数 Function(){ [native code] }
                console.log(new Date().constructor);            // 返回函数 Date()    { [native code] }
            }
          </script>

          <!--  JavaScript 变量可以转换为新变量或其他数据类型:
                通过使用 JavaScript 函数或通过 JavaScript 自身自动转换 -->
        
        <!-- 12.1 将数字转换为字符串 -->

        <button onclick="ljs_12_1_1()">将数字转换为字符串</button>
        <script>
            function ljs_12_1_1(){
                var x=123;          //数字
                var y=x.toString(); //字符串
                var z=String(x);    //字符串

                console.log(typeof y);//输出字符串类型
                console.log(typeof z);//输出字符串类型

//                更多数字转换为字符串的方法：
//                   toExponential()	把对象的值转换为指数计数法。
//                   toFixed()	把数字转换为字符串，结果的小数点后有指定位数的数字。
//                   toPrecision()	把数字格式化为指定的长度。


//                更多将日期转换为字符串的方法：
//                  getDate()	从 Date 对象返回一个月中的某一天 (1 ~ 31)。
//                  getDay()	从 Date 对象返回一周中的某一天 (0 ~ 6)。
//                  getFullYear()	从 Date 对象以四位数字返回年份。
//                  getHours()	返回 Date 对象的小时 (0 ~ 23)。
//                  getMilliseconds()	返回 Date 对象的毫秒(0 ~ 999)。
//                  getMinutes()	返回 Date 对象的分钟 (0 ~ 59)。
//                  getMonth()	从 Date 对象返回月份 (0 ~ 11)。
//                  getSeconds()	返回 Date 对象的秒数 (0 ~ 59)。
//                  getTime()	返回 1970 年 1 月 1 日至今的毫秒数。
            }
        </script>

        <!-- 12.2 将字符串转换为数字 -->
         <button onclick="ljs_12_2_1()">将字符串转换为数字</button>
         <button onclick="ljs_12_2_2()">将布尔值转换为数字</button>

         <script>
            function ljs_12_2_1(){
                var x="123";       //字符串
                var y=Number(x);   //数字  全局方法 Number() 可以将字符串转换为数字。
                var z=+x;          //数字  一元运算符 Operator + 可用于将变量转换为数字：

                console.log(typeof y);//输出数字类型
                console.log(typeof z);//输出数字类型

//                更多将字符串转换为数字的方法：
//                   parseFloat()	将字符串转换为数字。
//                   parseInt()	    字符串转换为整数。
            }
            
            // 将布尔值转换为数字
            function ljs_12_2_2(){
                console.log(Number(true)); //输出 1
                console.log(Number(false));//输出 0
            }
         </script>

         <!-- javascript会自动转换类型 -->
         <!-- 当 JavaScript 尝试操作一个 "错误" 的数据类型时，会自动转换为 "正确" 的数据类型。 -->
         <button onclick="ljs_12_3_1()">javascript会自动转换类型</button>
         <script>
            function ljs_12_3_1(){
                console.log(5 + null);    // 返回 5         null 转换为 0
                console.log("5" + null);  // 返回"5null"   null 转换为 "null"
                console.log("5" + 1);     // 返回 "51"      1 转换为 "1"  
                console.log("5" - 1);     // 返回 4         "5" 转换为 5
            }
            //当你尝试输出一个对象或一个变量时 JavaScript 会自动调用变量的 toString() 方法。
         </script>

    <!-- 13:错误处理 -->
         <button onclick="ljs_13_0_1()">try...catch</button>
         <script>
            //try语句用于测试代码块的错误
            //catch语句用于处理错误
            //throw语句用于创建自定义错误
            //finally语句用于执行一些 statements，无论 try...catch 结果如何。

            var ljs_13_0_1_text = "";
            function ljs_13_0_1(){
                try{
                    adddlert("Welcome guest!");//这个语句是存在错误的。
                }
                catch(err){
                    ljs_13_0_1_text = err.message;
                    console.log(ljs_13_0_1_text);//输出错误信息：adddlert is not defined
                }
            }
</script>

    <button onclick="ljs_13_0_2()" >执行finally</button>
    <script>
        function ljs_13_0_2(){
            try{
                adddlert("Welcome guest!");
            }
            catch(err){
                ljs_13_0_1_text = err.message;
                console.log(ljs_13_0_1_text);
            }
            finally{
                console.log("finally 1");//输出finally,此时try语句执行错误，catch语句执行，finally语句执行
            }

            try{
                alert("Welcome guest!");
            }
            catch(err){
                ljs_13_0_1_text = err.message;
                console.log(ljs_13_0_1_text);
            }
            finally{
                console.log("finally 2");//输出finally,此时try语句执行正常，catch语句不执行，finally语句执行
            }
        }
    </script>

    <!-- throw语句允许我们创建自定义错误 即 创建和抛出exception-->
     <button type="button" onclick="ljs_13_0_3()">自定义错误:给出5-10之间的数</button>
     <input id="ljs_13_0_3_input" type="text">
     
     <script>
     function ljs_13_0_3() {
         var x;
         x = document.getElementById("ljs_13_0_3_input").value;
         try { 
             if(x == "")  throw "值为空";
             if(isNaN(x)) throw "不是数字";
             if(x < 5)    throw "太小";
             if(x > 10)   throw "太大";
            }
         catch(err) {
             console.log("错误："+err);
         }finally {
             console.log("finally");//不论结果如何都会输出
         }
     }
     </script>

     <!-- 14 关于javascript 声明提升（hoisting 即函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部。） -->
      <div style="border: 3px solid red;">
        <p>以下两个按钮输出一致的结果。</p>
        <button onclick="ljs_14_0()">javascript 声明提升[1]</button>
        <button onclick="ljs_14_1()" >javascript 声明提升[2]</button>
        <script>
            // JavaScript 中，函数及变量的声明都将被提升到函数的最顶部。
            // 变量可以在使用后声明，也就是变量可以先使用再声明。

            function ljs_14_0(){
                x = 5;
                console.log(x);//输出5
                var x;
            }
            function ljs_14_1(){
                var x;
                x = 5;
                console.log(x);//输出5
            }
        </script>
    </div>
    <!-- 但是，javascript的初始化不会被提升 -->
     <div style="border: 3px solid red;">
        <p>以下两个按钮输出不一致的结果。</p>
        <button onclick="ljs_14_2()">javascript 声明提升[3]</button>
        <button onclick="ljs_14_3()" >javascript 声明提升[4]</button>
        <script>
            function ljs_14_2(){
                console.log(x);//输出undefined
                var x = 5;
            }
            function ljs_14_3(){
                var x = 5;
                console.log(x);//输出5
            }
        </script>
     </div>
     <!-- 注意： JavaScript 严格模式(strict mode)不允许使用未声明的变量。 -->

     <!-- 15 关于javascript 严格模式(strict mode) -->
      <div style="border: 3px solid red;">
        <p>该容器内脚本均使用严格模式（strict mode）</p>
        <button onclick="ljs_15_0()">javascript 严格模式[1]</button>
        <button onclick="ljs_15_1()" >javascript 严格模式[2]</button>
        <button onclick="ljs_15_2()">javascript 严格模式[3]</button>
        <script>
            function ljs_15_0(){//不使用严格模式
                x = 5;
                console.log(x);//输出5
            }
            function ljs_15_1(){
                "use strict";//只在函数内使用严格模式
                ljs_15_0_1 = 5;
                console.log(ljs_15_0_1);//输出undefined
            }
        </script>
        <script>
            "use strict";//全局使用严格模式
            function ljs_15_2(){
                ljs_15_0_2 = 5;
                console.log(ljs_15_0_2);//输出undefined
            }
        </script>
        <!-- 严格模式用于
                        消除 Javascript 语法的一些不合理、不严谨之处，减少一些怪异行为。
                        消除代码运行的一些不安全之处，保证代码运行的安全。
                        提高编译器效率，增加运行速度。
                        为未来新版本的Javascript做好铺垫。 
        -->

        <!-- 严格模式存在以下限制：
         1、不允许使用未声明的变量
         2、不允许删除对象和变量
         3、不允许删除函数
         4、不允许变量重名
         5、不允许使用八进制
         6、不允许使用转义字符
         7、不允许对只读属性赋值
         8、不允许对一个使用getter方法读取的属性进行赋值
         9、不允许删除一个不允许删除的属性
         10、变量名不允许使用eval字符串
         11、变量名不允许使用arguments字符串
         12、不允许使用with语句 如   with (Math){x = cos(2)};
         13、在作用域 eval() 创建的变量不能被调用
         14、禁止this关键字指向全局对象。因此使用构造函数时，如果忘了加new，this不再指向全局对象，而是报错。
         -->
        
        <!-- 附：use strict只允许出现在脚本或函数的开头 -->

      </div>

      <!-- 关于javascript存在的使用误区，可以参考https://www.runoob.com/js/js-mistakes.html -->

      <!-- 16 关于javascript表单 -->
        
         <!-- 16.1 html表单验证 -->
          <div style="border: 3px solid red;">
            【1】判断表单字段是否存在
            <form action="" name="ljs_16_0_form">
                <input type="text" name="ljs_16_0_input">
                <input type="submit" value="提交" onclick="ljs_16_1_1()">
            </form>
                
            <script>
                function ljs_16_1_1(){
                    var x = document.forms["ljs_16_0_form"]["ljs_16_0_input"].value;
                    if (x == "") {
                        alert("Name must be filled out");
                        return false;
                    }else{
                        alert("Name ["+x+"] is filled out");
                        return false;
                    }
                }
            </script>

            【2】验证输入的数字
            <form action="" name="ljs_16_1_form">
                <input type="text" name="ljs_16_1_input">
                <input type="submit" value="提交" onclick="ljs_16_1_2()">
            </form>
            <script>
                function ljs_16_1_2(){
                    var x = document.forms["ljs_16_1_form"]["ljs_16_1_input"].value;
                    if (isNaN(x) || x < 1 || x > 10) {
                        alert("Input not valid");
                        return false;
                    }else{
                        alert("Input ["+x+"] is valid"+" 满足条件：在1-10之间");
                        return false;
                    }
                }
            </script>

            【3】html表单自动验证
            <!-- html表单验证可以通过浏览器自动完成 -->
             <!-- 如果表单字段（fname）的值为空 ， required属性会阻止表单提交 -->
              <form action="" name="ljs_16_2_form">
                First name: <input type="text" name="fname" required>
                <!-- 如果不填入值，浏览器会提醒该字段为必填。 -->
                <input type="submit" value="提交">
              </form>
                </input>
              </form>

            <!-- 服务端数据验证是在数据提交到服务器上后再验证 -->
            <!-- 客户端数据验证是在数据发送到服务器前，在浏览器上完成验证 -->

            <!-- 
                关于HTML约束验证
                HTML5新增了HTML表单的验证方式：约束验证【constraint validation】
                约束验证是表单被提交时浏览器用来实现验证的一种算法
                HTML约束验证基于 HTML输入属性 CSS伪类选择器 DOM属性和方法
            -->
                
            <!-- 约束验证HTML输入属性 -->
            <!-- 属性名      ｜    描述                       -->
            <!-- disabled   ｜禁用表单字段               -->
            <!-- max        ｜设置输入字段的最大值           -->
            <!-- min        ｜设置输入字段的最小值          -->
            <!-- pattern    ｜设置输入字段的验证模式      -->
            <!-- type       ｜设置输入字段的类型          -->
            <!-- required   ｜设置输入字段是否为必填字段 -->
            
            <!-- 关于html输入属性，详见https://www.runoob.com/html/html5-form-attributes.html -->
            
            <!-- 约束验证CSS伪类选择器 -->
            <!-- :disabled   ｜禁用表单字段              -->
            <!-- :invalid    ｜输入字段无效              -->
            <!-- :valid      ｜输入字段有效             -->
            <!-- :required   ｜设置输入字段是否为必填字段 -->
            <!-- :optional   ｜设置输入字段是否为可选字段 -->

            <!-- 关于CSS伪类，详见https://www.runoob.com/css/css-pseudo-classes.html -->
          </div>

          <!-- 16.2 javascript表单验证 -->
            <div style="border: 3px solid red;">
                <!-- 16.2.1 检查用户是否已填写必填项目 -->
                 <form action="" name="ljs_16_2_1_form">
                     input 1 【必填】
                     <input type="text" name="ljs_16_2_1_input" required>
                     input 2 【可选】
                     <input type="text" name="ljs_16_2_1_input2">
                     <input type="submit" value="提交" onclick="ljs_16_2_1_1()">
                 </form>
                     
                 <script>
                     function ljs_16_2_1_1(){
                         var x = document.forms["ljs_16_2_1_form"]["ljs_16_2_1_input"].value;
                         var y = document.forms["ljs_16_2_1_form"]["ljs_16_2_1_input2"].value;
                         
                         if (x == "") {
                             alert("No.1 must be filled out");
                             return false;
                         }else{
                            if(y != ""){
                                alert("Name ["+x+"] is filled out"+" and "+"name ["+y+"] is filled out");
                            }else{
                                alert("Name ["+x+"] is filled out");
                            }
                         }
                     }
                 </script>

                 <!-- 16.2.2 email验证 -->
                  <form action="" name="ljs_16_2_2_form">
                     email
                     <input type="email" name="ljs_16_2_2_input">
                     <input type="submit" value="提交" onclick="ljs_16_2_2_1()"></input>
                     </input>
                  </form>

                  <script>
                      function ljs_16_2_2_1(){
                          var x = document.forms["ljs_16_2_2_form"]["ljs_16_2_2_input"].value;
                          var atpos=x.indexOf("@");
                          var dotpos=x.lastIndexOf(".");
                          if (atpos<1 || dotpos<atpos+2 || dotpos+2>=x.length){
                            //算法：输入的数据必须包含 @ 符号和点号(.)。同时，@ 不可以是邮件地址的首字符，并且 @ 之后需有至少一个点号
                              alert("Email地址无效");
                              return false;
                          }else{
                              alert("Email ["+x+"] is filled out");
                              return false;
                          }
                      }
                  </script>

                  <!-- 16.2.3 验证API  -->
                   <!-- HTMLSelectElement.checkValidity() 会检查元素是否有任何输入约束条件，并且检查值是否符合约束条件。 
                    如果值是不符合约束条件的，浏览器就会在该元素上触发一个可以撤销的 invalid 事件（返回false）。 -->
                    <!-- 
                        setCustomValidity() 用于设置input元素的validationMessage属性以【自定义错误提示信息】的方法。
                        使用setCustomValidity设置自定义提示后，validity.customeError属性就会变成true，checkValidity()方法就会总是返回false。 
                        如果要重新判断需要取消自定义提示，方式如下：
                        setCustomValidity('') 
                        setCustomValidity(null) 
                        setCustomValidity(undefined)
                    -->         
                    <input id="id1" type="number" min="100" max="300" required>
                    <button onclick="ljs_16_2_3()">验证</button>
                                          
                    <script>function ljs_16_2_3() {
                        var inpObj = document.getElementById("id1");
                        if (inpObj.checkValidity() == false) {
                            alert(inpObj.validationMessage);
                        }else{
                            alert("输入值["+inpObj.value+"]有效");
                        }
                    }</script> 
                    
                    <!-- 约束验证 DOM 属性
                    validity	        布尔属性值，返回 input 输入值是否合法
                    validationMessage	浏览器错误提示信息
                    willValidate	    指定 input 是否需要验证 -->

                    <!-- 
                    input 元素的 validity 属性包含一系列关于 validity 数据属性:
                        customError	    设置为 true, 如果设置了自定义的 validity 信息。
                        patternMismatch	设置为 true, 如果元素的值不匹配它的模式属性。
                        rangeOverflow	设置为 true, 如果元素的值大于设置的最大值。
                        rangeUnderflow	设置为 true, 如果元素的值小于它的最小值。
                        stepMismatch	设置为 true, 如果元素的值不是按照规定的 step 属性设置。
                        tooLong	        设置为 true, 如果元素的值超过了 maxLength 属性设置的长度。
                        typeMismatch	设置为 true, 如果元素的值不是预期相匹配的类型。
                        valueMissing	设置为 true，如果元素 (required 属性) 没有值。
                        valid	        设置为 true，如果元素的值是合法的。 
                    -->
                    
                    <input id="id1" type="number" max="100">
                    <button onclick="myFunction()">验证</button>
 
                    <p id="demo"></p>
 
                    <script>
                        function myFunction() {
                            var txt = "";
                            if (document.getElementById("id1").validity.rangeOverflow) {
                                txt = "输入的值太大了";
                            }
                             document.getElementById("demo").innerHTML = txt;
                            }
                    </script>

                        <input id="id1" type="number" min="100" required>
                        <button onclick="myFunction()">OK</button>
 
                        <p id="demo"></p>
 
                        <script>function myFunction() {
                            var txt = "";
                            var inpObj = document.getElementById("id1");
                            if(!isNumeric(inpObj.value)) {
                                txt = "你输入的不是数字";
                            } else if (inpObj.validity.rangeUnderflow) {
                                txt = "输入的值太小了";
                            } else {
                                txt = "输入正确";
                            }
                            document.getElementById("demo").innerHTML = txt;
                        }

                        // 判断输入是否为数字
                        function isNumeric(n) {
                            return !isNaN(parseFloat(n)) && isFinite(n);
                        }</script>
                    </div>

                    
</body> 
</html>